home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / develop™ Technical Journal / develop Issue 24 code / Scriptable Database 1.0a11.sea / Scriptable Database 1.0a11 / Base / Exceptions.h / Exceptions.h
Encoding:
C/C++ Source or Header  |  1995-10-18  |  9.0 KB  |  325 lines  |  [TEXT/MPCC]

  1. /*
  2.     File:        Exceptions.h
  3.  
  4.     Contains:    exception handling macros
  5.  
  6.     Written by:    Bruce Horn, Steve Capps, Larry Kenyon, John Meier, scott douglass, Darin Adler,
  7.                 Paul Mercer, Bryan Stearns, Dave Owens
  8.                 
  9.                 Andy Nicholas
  10.  
  11.     Copyright:    © 1988-1995 by Apple Computer, Inc., all rights reserved.
  12.  
  13.          <2>     2/24/95    ga        
  14. */
  15.  
  16. #ifndef Exceptions_h
  17. #define Exceptions_h
  18.  
  19. #include <Types.h>
  20. #include <setjmp.h>
  21. // #include <Memory.h>
  22.  
  23. // #include <Errors.h>
  24.  
  25. // #include "List.h"                // needed for Loop stuff
  26.  
  27. #ifdef METROWERKSPOWERPC
  28. struct DestructorChain;            // Forward declaration of Metrowerks local destructor chain type
  29. #endif
  30.  
  31. class TException;
  32.  
  33. extern TException*     gExceptionStack;
  34. extern long            gExceptionMessage;
  35. extern long            gExceptionError;
  36.  
  37. void    Fail(long, long message);
  38. void    FailErr(long);
  39. void    FailAgain();
  40. void    FailNil(void*);
  41.  
  42. const long nilPtrErr = -110;    // Same as memAdrErr--odd or out of range
  43. const OSErr ePointerNil                = -110;
  44. const OSErr eGeneralErr                = -1;
  45. const OSErr eAssertionFailure        = -30000;
  46. const OSErr eRequirementNotMet        = -30001;
  47. const OSErr eValueOutOfRange        = -30002;
  48. const OSErr eIndexOutOfRange        = -30003;
  49. const OSErr eLinksCorrupt            = -30004;
  50. const OSErr eDataCorrupt            = -30005;
  51. const OSErr eWrongDataType            = -30006;
  52. const OSErr eFunctionNotHandledByClass = -30007;
  53.  
  54. //----------------------------------------------------------------------------------------
  55. // Except_Error: 
  56. //----------------------------------------------------------------------------------------
  57. inline long    Except_Error()
  58.         { 
  59.         return gExceptionError; 
  60.         }
  61.  
  62. //----------------------------------------------------------------------------------------
  63. // Except_Message: 
  64. //----------------------------------------------------------------------------------------
  65. inline long    Except_Message()
  66.         {
  67.         return gExceptionMessage; 
  68.         }
  69.  
  70. //----------------------------------------------------------------------------------------
  71. // ExpectError: 
  72. //----------------------------------------------------------------------------------------
  73. inline void ExpectError(OSErr error)
  74.         { 
  75.         if (Except_Error() != error) FailAgain(); 
  76.         }
  77.  
  78. //----------------------------------------------------------------------------------------
  79. // FailErr: 
  80. //----------------------------------------------------------------------------------------
  81. inline void FailErr(long error)
  82.     {
  83.     if (error != noErr)
  84.         Fail(error, 0);
  85.     }
  86.  
  87. //----------------------------------------------------------------------------------------
  88. // FailNil: 
  89. //----------------------------------------------------------------------------------------
  90. inline void FailNil(void *pointer)
  91.     {
  92.     if (pointer == nil)
  93.         FailErr(nilPtrErr);
  94.     }
  95.  
  96. //========================================================================================
  97. // CLASS TExceptionAction
  98. //
  99. // Exception action objects may be attached to the current exception handler; if
  100. // an exception is thrown, then the virtual method 'CatchException' is called, and
  101. // the exception-action object may do whatever cleanup it needs to.
  102. //========================================================================================
  103.  
  104. class TExceptionAction
  105.     {
  106. public:
  107.     virtual void        CatchException() = 0;
  108.     
  109.     TExceptionAction*    GetNextExceptionAction() { return fNextAction; }
  110.     void                SetNextExceptionAction(TExceptionAction* nextAction) { fNextAction = nextAction; }
  111.  
  112. private:
  113.     TExceptionAction*    fNextAction;
  114.     };
  115.     
  116.         
  117. //========================================================================================
  118. // CLASS TException
  119. //========================================================================================
  120.  
  121. class TException
  122.     {
  123. public:
  124.     
  125.     //
  126.     // --- Methods -------------------------------------------------------------------------------------
  127.     //
  128.                         TException();                // to set up next & fired
  129.                          ~TException();                // to remove from the exceptions stack
  130.  
  131.     void                AddExceptionAction(TExceptionAction* exceptAction);                // Add an exception action object to the the exception frame
  132.     TExceptionAction*    RemoveExceptionAction(TExceptionAction* exceptAction = nil);    // Remove a loop from the exception frame 
  133.     
  134.     //
  135.     // --- Fields --------------------------------------------------------------------------------------
  136.     //
  137.     jmp_buf                fEnv;                    // jmp_buf has to be first
  138.     
  139. #ifdef SIXTYEIGHTK
  140.     long                fA5;                    // Save the current A5
  141. #endif
  142.  
  143. #ifdef METROWERKSPOWERPC
  144.     DestructorChain*     fLocalDestructorChain;    // • temporary Metrowerks hack
  145. #endif
  146.  
  147.     TExceptionAction*    fExceptionAction;        // A pointer to the first exception action object
  148.     TException*            fPrevious;                // A pointer to the previous exception frame on the stack
  149.     
  150.     Boolean                fFired;    
  151.     };
  152.  
  153.  
  154. //----------------------------------------------------------------------------------------
  155. // TException::AddExceptionAction:
  156. //
  157. // Insert 'exceptAction' into the linked-list of exception-actions hanging off the
  158. // exception frame
  159. //----------------------------------------------------------------------------------------
  160. inline void TException::AddExceptionAction(TExceptionAction* exceptAction)
  161.     {
  162.     exceptAction->SetNextExceptionAction(fExceptionAction);
  163.     fExceptionAction = exceptAction;
  164.     }
  165.  
  166. //----------------------------------------------------------------------------------------
  167. // TException::RemoveExceptionAction:
  168. //
  169. // Remove a single loop from the linked-list of loops hanging off the exception frame
  170. //----------------------------------------------------------------------------------------
  171. inline TExceptionAction* TException::RemoveExceptionAction(TExceptionAction* exceptAction /* = nil */)
  172.     {
  173.     if((exceptAction == fExceptionAction) || (exceptAction == nil))
  174.         {
  175.         exceptAction = fExceptionAction;
  176.         fExceptionAction = fExceptionAction->GetNextExceptionAction();
  177.         }
  178.     else
  179.         {
  180.         TExceptionAction* actionList;
  181.         
  182.         while(actionList != nil)
  183.             {
  184.             TExceptionAction* nextAction = actionList->GetNextExceptionAction();
  185.             if(nextAction == exceptAction)
  186.                 {
  187.                 actionList->SetNextExceptionAction(nextAction->GetNextExceptionAction());
  188.                 actionList = nil;
  189.                 }
  190.             else
  191.                 actionList = nextAction;
  192.             }
  193.         }
  194.     
  195.     return exceptAction;
  196.     }
  197.  
  198.  
  199. //
  200. // TRY/EXCEPT/ENDTRY Usage:
  201. //
  202. // Advantage:        Every failure handler has its own scope
  203. // Disadvantage:    Requires ugly "ENDTRY", and forgetting it
  204. //                    causes strange errors much later in the file
  205. //
  206. //        TRY
  207. //            {
  208. //            // do something
  209. //            FailErr(SomeFnReturningOSErr());
  210. //            }
  211. //        EXCEPT
  212. //            {
  213. //            OSErr err = Except_Error();
  214. //
  215. //            // clean up
  216. //            FailAgain();
  217. //            }
  218. //        ENDTRY
  219. //
  220. #define TRY { TException exceptions_data; \
  221.             if (setjmp(exceptions_data.fEnv) == 0) {
  222. #define EXCEPT } else {
  223. #define ENDTRY } }
  224. #define NOREGISTER(x)    ((void)&x)
  225.  
  226. //
  227. // Try/Catch/Throw Usage:
  228. //
  229. // Advantage:        No ugly "ENDTRY"; looks very similar to C++ try/catch
  230. // Disadvantage:    Must wrap each failure handler in its own scope,
  231. //                    or you will get an error "fi defined twice"
  232. //
  233. //        OSErr err = noErr;
  234. //
  235. //        Try
  236. //            {
  237. //            // do something
  238. //            FailErr(SomeFnReturningOSErr());    // "Throw" is unconditional
  239. //            }
  240. //        Catch(err)
  241. //            {
  242. //            // clean up
  243. //            Throw(err);
  244. //            }
  245. //
  246. #define Try            TException fi; if(setjmp(fi.fEnv) == 0) for(; gExceptionStack == &fi; gExceptionStack = fi.fPrevious, fi.fFired = true)
  247. #define Catch(err)    else if((err = (OSErr) Except_Error()) != noErr)
  248. #define Throw(err)    Fail(err, 0)
  249. #define Require(b)    if(b == false) Throw(-1)
  250.  
  251. //
  252. // try/catch/throw usage:
  253. //
  254. // Advantage:        Supported by the compiler, so it's portable
  255. // Disadvantage:    Most of our compilers don't provide exception handling
  256. //
  257. //        try
  258. //            {
  259. //            // do something
  260. //            FailErr(SomeFnReturningOSErr());    // "throw" is unconditional, so we still need a FailErr
  261. //            }
  262. //        catch(OSErr err)
  263. //            {
  264. //            // clean up
  265. //            throw(err);
  266. //            }
  267. //
  268.  
  269. //
  270. // How to combine Try/Catch with try/catch to form an 
  271. // exception mechanism that works on compilers that
  272. // do support exception handling, and also build on
  273. // compilers that do not support it:
  274. //
  275. // Define a type "ExceptionOSErr", which is just an
  276. // OSErr.   If exceptions are supported, ExceptionOSErr
  277. // is #defined to be OSErr.  If it is not supported,
  278. // then it is #defined to be nothing.
  279. //
  280. // The catch is that you must always use the type
  281. // ExceptionOSErr in your catch blocks, you must
  282. // always throw OSErrs, and the variable in the
  283. // catch block must always be exceptionErr.
  284. //
  285. //        try
  286. //            {
  287. //            // do something
  288. //            FailErr(SomeFnReturningOSErr());    // "throw" is unconditional, so we still need a FailErr
  289. //            }
  290. //        catch(ExceptionOSErr exceptionErr)
  291. //            {
  292. //            // clean up
  293. //            throw(err);
  294. //            }
  295. //
  296. // The problem is that our exception handler saves extra state
  297. // (TopMapHandle, CurMap, CurApRefNum, and Zone) that will NOT
  298. // be saved by a compiler-supported exception handler.
  299. //
  300. // I need to look into ways of patching into the 'try/catch'
  301. // process...
  302. //                - ga
  303. // 
  304. // EXCEPTIONSSUPPORTED
  305. //
  306.  
  307. #ifdef FUTURECODE // Don't use this yet...
  308.  
  309. // EXCEPTIONSSUPPORTED
  310.  
  311. #define ExceptionOSErr OSErr
  312.  
  313. // !EXCEPTIONSSUPPORTED
  314.  
  315. #define ExceptionOSErr OSErr
  316.  
  317. #define try            OSErr exceptionErr; TException fi; if(setjmp(fi.fEnv) == 0) while(fi.fFired == false)
  318. #define catch        else if((err = Except_Error()) != noErr)
  319. #define throw(err)    Fail(err, 0)
  320.  
  321. #endif // Don't use this yet
  322.  
  323. #endif
  324.  
  325.